package gameComponents;
/**
 * This class is responsible for running the knight's tour game
 * @author Selman Selman 
 * Last update : January 30, 2010
 * @modified by Selman Selman and Jordan Beland
 */
import gamePieces.Knight;

import java.io.IOException;
import java.util.Scanner;
import java.awt.Point;
import java.util.ArrayList;


/**
 * Game engine for Knight's Tour. Utilized by Controller to carry out
 * the playing of the game.
 * @author Jordan
 *
 */
public class KnightGame extends SuperGame{

	private Board b;
	private static Knight n;
	private int count = 0;
	private boolean grid[][]; // this is a grid used by knight game
	private Player player;
	
	
	 /**
	  * Constructor for KnightGame. Initializes board object, boolean grid, and player object with a default id of 1.
	  * does NOT initialize a Knight object.
	  * 
	  * @author Selman Selman
	  */
	public KnightGame(){
		b = new Board();
		grid = new boolean[Board.SIZE][Board.SIZE];
		player = new Player(1); // giving it an id of 1 does not force it to go lower case in toString()
	}
	
	/**
	 * This method is only used for testing
	 * @return grid
	 * @author Selman Selman
	 */
	
	public boolean[][] getGrid(){
		return grid;
	}
	
	/**
	 * Main method that creates a KnightGame object and calls play().
	 * 
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		KnightGame g = new KnightGame(); //new game being created
		g.play(); //invokes play to prompt the user to play the game
	}
	
	/**
	 * Checks if the user has no more possible moves which means he/she lost
	 * @return true if he lost , false otherwise
	 * @modified by Selman Selman
	 */
	public boolean checkIfLost(){
		ArrayList<Point> p = n.possibleMoves(); //get all possible moves
		for (Point pt : p){ // loops through all possible moves
			if (!(grid[(int) pt.getX()][(int) pt.getY()] == true)){ //checks if possible move to a cell that has not been visited
				return false;
			}
		}
		return true;
	}
	
	/**
	 * A helper method also used in play() to print all possible moves of the knight
	 * @param n of type Knight
	 */
	private static void printPossMoves(Knight n){
		System.out.println("Your possible moves are: ");
		ArrayList<Point> m = n.possibleMoves(); //gets the possible moves after it calculates it
		for (Point p : m){ //loops through each point
			System.out.print("(" + p.getX()+ ", " + p.getY() + ")"); //print it out to the user
		}
		System.out.println("\n");
	}
	
	/**
	 * A helper method that is used in play() to perform the first move of knight. This is where the
	 * Knight instance variable is initialized.
	 * 
	 * @param i of type String
	 * @throws IOException
	 */
	private void firstPlay(String i) throws IOException{
		int x = Board.convertX(i);
		int y = Board.convertY(i);
		if(!(x >= Board.SIZE) && !(x < 0) && !(y >= Board.SIZE) && !(y < 0)){
			n = new Knight(x, y, player);
			count += 1;
			b.placePiece(x, y, "N", player);
		}
	}
	
	/**
	 * This is a helper function that checks if cell is visited and checks if move is legal 
	 * this function is separate and public due to test purposes 
	 * @return true if cell is visited, false otherwise
	 * @author Selman Selman
	 */
	public boolean checkIfVisited(int x, int y){
		return grid[x][y];
	}
	
	/**
	 * The Play method. This method is responsible for the running the game, getting input from the user,
	 * and looping until the game has won, lost, or player exits.
	 * 
	 * @throws IOException
	 */
	public void play() throws IOException{
		Scanner scan = new Scanner(System.in);
		System.out.println("-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-");
		System.out.println("      Welcome to the Knight's Tour Game");
		System.out.println("-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-");
		b.print(); // print original empty grid
		System.out.println("Press q anytime you want to exit the game");
		System.out.println("Please enter where do you want to place the Knight. Ex: A4");
		String input = scan.next();
		firstPlay(input);
		printBoard();
		System.out.println("Please enter where you would like to move Knight");
		System.out.println("For possible moves type p\n");
		input = scan.next();
		//while user does not press q game will keep running
		// asks user for his next move and prints an update of grid every time a move is made
		while (!input.equals("q")){
			if (input.equals("q")){
				break;
			} else{
				if(input.equals("p")){
					printPossMoves(n);
				}
				else {
					int x = Board.convertX(input);
					int y = Board.convertY(input);
					if(n.checkIfLegal(x,y) && grid[x][y] != true){ //makes sure move is legal
						grid[n.getX()][n.getY()] = true;
						//b.placePiece(n.getX(), n.getY(), "X"); //mark the original cell with X
						n.move(x, y); //move knight
						count +=1;
						//b.placePiece(x, y, "N"); //place knight at that cell
					}
					else{
						System.out.println("Illegal Move try again!\n");
					}
					printBoard();
					if(count == 64){
						System.out.println("You won =*=");
						break;
					}
					if(checkIfLost()){
						System.out.println("You Lost the game :@:@\nNo more possible moves");
						break;
					}
				}
				System.out.println("Where do you want to move the Knight?\n");
				input = scan.next();
			}
		}
		//promotes the user to play again
		System.out.println("Would you like to play again?(y/n)");
		String input2 = scan.next();
		if (input2.equals("y")){
			KnightGame game = new KnightGame();
			game.play();
		}
	}
	/**
	 * This method is used for the graphical display of the board for the user to interact with.
	 * 
	 */
	public void printBoard(){
		String result = "  A  B  C  D  E  F  G  H \n";
		 for(int j = 0; j < Board.SIZE; j++){
			 result += j+1;
	            for(int i = 0; i < Board.SIZE; i++){
	            	if(grid[i][j] == true){
	            		result += "|X|";
	            	} else if (i == n.getX() && j == n.getY()){
	            		result += "|N|";
	            	}
	            	else{
	            		result += "|_|";
	            	}
	            	
	            }
	            result += "\n";
		 }
		 System.out.print(result);
	}

}


